home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / applications / wp / ged11.lha / Install / data / main / GoldED / API / spell / main.c next >
C/C++ Source or Header  |  1994-08-12  |  22KB  |  729 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client example code, ©1994 Dietmar Eilert. Dice:
  4.  
  5.  dcc main.c -// -proto -mi -r -2.0 -l reqtoolss.lib -o ram:spell
  6.  
  7.  ENGLISH
  8.  
  9.  Note: Compiling this code requires reqtools includes & reqtools linker
  10.        libraries. The ReqTools library is © Nico François.
  11.  
  12.  The following code adds spell checking capabilities to GoldED. It is  based  on
  13.  the  ISpell package and the ISpell dictionary (available on Fish disks). ISpell
  14.  has to be installed properly (within a valid command path) before you  can  use
  15.  this  API  client.  This example uses synchronous ARexx communication: Requests
  16.  are PutMsg()'ed to GoldED's port, followed by a WaitPort() to get the  editor's
  17.  response.  This  works  fine since we need no ARexx communication after the API
  18.  link has been established. If there were ARexx communication with GoldED  AFTER
  19.  the link has been established (i.e. after sending the 'API PORT=...' command to
  20.  register with GoldED), we would have  to  use  an  asynchronous  design  beeing
  21.  capable  of  answering  incoming  API  messages while waiting for completion of
  22.  ARexx requests sent to GoldED.
  23.  
  24.  Note: La compilation de ce code requiert les includes et les bibliothèques de
  25.        liaison reqtools. La bibliothèque ReqTools est © Nico François.
  26.  
  27.  FRENCH
  28.  
  29.  Le code suivant ajoute des fonctions de correction orthographique à GoldED.  Il
  30.  est  basé  sur  le  pack  Ispell  et sur le dictionnaire Ispell (disponible sur
  31.  disquettes Fish). ISpell doit être  installé  proprement  (à  l'intérieur  d'un
  32.  chemin  de  commande valide) avant que vous ne puissiez utiliser le client API.
  33.  Cet exemple  utilise  la  communication  ARexx  synchrone:  les  requêtes  sont
  34.  PutMsg()'ées  sur  le  port  de  GoldED,  suivies d'un WaitPort() pour avoir la
  35.  réponse de l'éditeur. Ceci fonctionne très bien comme nous n'avons  pas  besoin
  36.  de  communications  ARexx  après l'établissement de la liaison API (c-à-d après
  37.  l'envoi de la commande  'API  PORT=...'  pour  s'enregistrer  à  GoldED),  nous
  38.  aurions  dû  utiliser  un  système  asynchrone  étant  capable  de répondre aux
  39.  messages API arrivants, tout en attendant la fin des requêtes ARexx envoyées  à
  40.  GoldED.
  41.  
  42.   -------------------------------------------------------------------------------
  43. */
  44.  
  45. /// "includes"
  46.  
  47. #define Prototype extern
  48.  
  49. #include <exec/exec.h>
  50. #include <string.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <dos/dos.h>
  54. #include <dos/dostags.h>
  55. #include <dos/rdargs.h>
  56. #include <intuition/intuition.h>
  57. #include <utility/tagitem.h>
  58. #include <libraries/gadtools.h>
  59. #include <rexx/errors.h>
  60. #include <rexx/rxslib.h>
  61. #include <clib/exec_protos.h>
  62. #include <clib/dos_protos.h>
  63. #include <clib/graphics_protos.h>
  64. #include <clib/intuition_protos.h>
  65. #include <clib/diskfont_protos.h>
  66. #include <clib/rexxsyslib_protos.h>
  67. #include <clib/gadtools_protos.h>
  68. #include <clib/reqtools_protos.h>
  69. #include <clib/alib_protos.h>
  70. #include <devices/audio.h>
  71. #include "golded:api/include/golded.h"
  72.  
  73. Prototype void   main(int, char **);
  74. Prototype BOOL   InitISpell(void);
  75. Prototype void   HandleAPI(BOOL, char *);
  76. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
  77. Prototype void   CheckWord(struct APIMessage *, struct MsgPort *, BOOL);
  78. Prototype void   Beep(void);
  79. Prototype UWORD  ComputeX(struct TextFont *, UWORD);
  80. Prototype UWORD  ComputeY(struct TextFont *, UWORD);
  81. Prototype char  *ShowSpell(char *, struct List *);
  82. Prototype struct Node *SearchNode(struct List *, UWORD);
  83.  
  84. struct Library *ReqToolsBase;
  85.  
  86. ///
  87. /// "main"
  88.  
  89. void
  90. main(int argc, char **argv)
  91. {
  92.     const char *version = "$VER: spell 1.3 (" __COMMODORE_DATE__ ")";
  93.  
  94.     if ((argc == 2) || (argc == 3)) {
  95.  
  96.         if (ReqToolsBase = (struct ReqToolsBase *)OpenLibrary("reqtools.library", 0)) {
  97.  
  98.             char *host;                              // name of GoldED's port
  99.             BOOL ask;                                // ask user if misspelled word detected ?
  100.  
  101.             ask  = (argc == 3);                      // the easy way ;-)
  102.             host = argv[--argc] + 5;                 // host name (HOST=...) always passed as last argument
  103.  
  104.             if (InitISpell())                        // launch ISpell
  105.                 HandleAPI(ask, host);                // register with GoldED
  106.  
  107.             CloseLibrary(ReqToolsBase);
  108.         }
  109.     }
  110.     else
  111.         puts("syntax error: SPELL ASK/S HOST/K");
  112.  
  113.     exit(0);
  114. }
  115.  
  116. ///
  117. /// "init"
  118.  
  119. /* -------------------------------- IntiISpell ---------------------------------
  120.  
  121.  Prepare ISpell. Return TRUE if successful.
  122.  
  123. */
  124.  
  125. BOOL
  126. InitISpell()
  127. {
  128.     if (FindPort("IRexxSpell"))
  129.  
  130.         return(TRUE);
  131.  
  132.     else {
  133.  
  134.         struct TagItem tags[] = {SYS_Output, NULL, SYS_Input, NULL, SYS_Asynch, TRUE, TAG_DONE};
  135.  
  136.         if (SystemTagList("ispell -r", tags) != -1) {
  137.  
  138.             UWORD n;
  139.  
  140.             for (n = 0; n < 100; n++, Delay(10))
  141.                 if (FindPort("IRexxSpell"))
  142.                     return(TRUE);
  143.         }
  144.     }
  145.  
  146.     puts("ISpell not available");
  147.  
  148.     return(FALSE);
  149. }
  150.  
  151. ///
  152. /// "api management"
  153.  
  154. /* --------------------------------- HandleAPI ---------------------------------
  155.  
  156.  Register with GoldED & handle incoming API messages.
  157.  
  158. */
  159.  
  160. void
  161. HandleAPI(ask, host)
  162.  
  163. BOOL ask;
  164. char *host;
  165. {
  166.     struct MsgPort *rexxPort, *apiPort;
  167.  
  168.     if (apiPort = CreateMsgPort()) {
  169.  
  170.         if (rexxPort = CreateMsgPort()) {
  171.  
  172.             char  command[255];
  173.             ULONG *result;
  174.  
  175.             sprintf(command, "API PORT=%ld MASK=%ld", apiPort, API_CLASS_ROOT | API_CLASS_KEY);
  176.  
  177.             if (result = SendRexxCommand(host, command, rexxPort, NULL)) {
  178.  
  179.                 if (*result == RC_OK) {
  180.  
  181.                     BOOL active = TRUE;
  182.  
  183.                     do {
  184.  
  185.                         struct APIMessage *apiMsg, *nextMsg;
  186.  
  187.                         while (!(apiMsg = (struct APIMessage *)GetMsg(apiPort)))
  188.                             WaitPort(apiPort);
  189.  
  190.                         do {
  191.  
  192.                             for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  193.  
  194.                                 if (nextMsg->api_State == API_STATE_NOTIFY) {
  195.  
  196.                                     switch (nextMsg->api_Class) {
  197.  
  198.                                         case API_CLASS_ROOT:
  199.  
  200.                                             switch (nextMsg->api_Action) {
  201.  
  202.                                                 case API_ACTION_DIE:
  203.  
  204.                                                     active = FALSE;
  205.                                                     break;
  206.  
  207.                                                 case API_ACTION_INTRODUCE:
  208.  
  209.                                                     static struct TagItem tags[] = {
  210.  
  211.                                                         API_Client_Name,      "spell",
  212.                                                         API_Client_Copyright, "©1994 Dietmar Eilert",
  213.                                                         API_Client_Purpose,   "Adds online spell checking",
  214.                                                         TAG_DONE
  215.                                                     };
  216.  
  217.                                                     nextMsg->api_Data = tags;
  218.                                                     break;
  219.  
  220.                                                 default:
  221.  
  222.                                                     nextMsg->api_Error = API_ERROR_UNKNOWN;
  223.                                             }
  224.  
  225.                                             break;
  226.  
  227.                                         case API_CLASS_KEY:
  228.  
  229.                                             switch (nextMsg->api_Action) {
  230.  
  231.                                                 case API_ACTION_VANILLAKEY:
  232.  
  233.                                                     // checks are performed after white space characters:
  234.  
  235.                                                     if ((UBYTE)nextMsg->api_Data < 'A')
  236.                                                         CheckWord(nextMsg, rexxPort, ask);
  237.  
  238.                                                     break;
  239.  
  240.                                                 default:
  241.  
  242.                                                     nextMsg->api_Error = API_ERROR_UNKNOWN;
  243.                                             }
  244.                                             break;
  245.  
  246.                                         default:
  247.  
  248.                                             nextMsg->api_Error = API_ERROR_UNKNOWN;
  249.                                     }
  250.                                 }
  251.                             }
  252.  
  253.                             ReplyMsg((struct Message *)apiMsg);
  254.  
  255.                         } while (apiMsg = (struct APIMessage *)GetMsg(apiPort));
  256.  
  257.                     } while (active);
  258.                 }
  259.             }
  260.  
  261.             SendRexxCommand("IRexxSpell", "EXIT", rexxPort, NULL);
  262.  
  263.             DeleteMsgPort(rexxPort);
  264.         }
  265.  
  266.         DeleteMsgPort(apiPort);
  267.     }
  268. }
  269.  
  270.  
  271. ///
  272. /// "check word"
  273.  
  274. /* --------------------------------- CheckWord ---------------------------------
  275.  
  276.  Check word. This function is called BEFORE  GoldED  actually  inserts  a  white
  277.  space  character  (space, colon, ...) at the current cursor position. We assume
  278.  the current position to  be  a  white  space  character  to  guarantee  correct
  279.  behavior if the user inserts a character into a word. If ISpell complains about
  280.  a word we will either issue a beep (ask = FALSE) or additionally display a list
  281.  of suggestions (<ask> = TRUE).
  282.  
  283.  Excerpt taken from man/ispell.1: If the word is  not  in  the  dictionary,  but
  284.  there  are  near  misses,  then the result line contains an '&', a space, and a
  285.  list of the near misses separated by spaces.
  286.  
  287.  Français
  288.  
  289.  Vérifie le mot. Cette fonction est appelée AVANT que GoldED n'insère un  espace
  290.  caractère  blanc (espace, colonne, ...) à la position actuelle du curseur. Nous
  291.  supposons que la position actuelle doit être un  caractère  espace  blanc  pour
  292.  garantir  un  comportement  normal si l'utilisateur insère un caractère dans un
  293.  mot. Si ISpell se plaint d'un mot, nous émettrons soit un  bip  (ask=FALSE)  ou
  294.  afficher une liste de suggestions (en option) (<ask> = TRUE).
  295.  
  296.  Exception tirée de man/ispell.1: si le mot n'est pas dans le dictionnaire, mais
  297.  qu'il  y a des mots très ressemblants, alors la ligne résultat contient un '&',
  298.  un espace, et une liste des mots les plus ressemblants séparés par des espaces.
  299.  
  300. */
  301.  
  302. void
  303. CheckWord(apiMsg, rexxPort, ask)
  304.  
  305. struct APIMessage *apiMsg;
  306. struct MsgPort    *rexxPort;
  307. BOOL   ask;
  308. {
  309.     struct EditConfig *config = apiMsg->api_Config;
  310.  
  311.     UWORD  column;
  312.     UBYTE  *buffer, *next;
  313.  
  314.     column = config->Column;
  315.     buffer = config->Current;
  316.  
  317.     // cursor placed directly after word ?
  318.  
  319.     if (column && (buffer[--column] > '@')) {
  320.  
  321.         static char word[1000], result[1000];
  322.  
  323.         UWORD wordLen;
  324.  
  325.         // find beginning of word
  326.  
  327.         for (next = buffer + column, wordLen = 1; column && (*(next - 1) > '@'); --column, --next)
  328.             ++wordLen;
  329.  
  330.         movmem(next, word, wordLen);
  331.  
  332.         word[wordLen] = 0;
  333.  
  334.         strins(word, "QUICKCHECK ");
  335.  
  336.         // make ISpell check word
  337.  
  338.         if (SendRexxCommand("IRexxSpell", word, rexxPort, result)) {
  339.  
  340.             if (stricmp(result, "ok")) {
  341.  
  342.                 Beep();
  343.  
  344.                 // send additional CHECK command to get further information
  345.  
  346.                 if (ask && SendRexxCommand("IRexxSpell", word + 5, rexxPort, result)) {
  347.  
  348.                     if (*result == '&') {
  349.  
  350.                         // translate ISpell result string into exec list
  351.  
  352.                         struct List list;
  353.                         struct Node *node,  *nextNode;
  354.                         char        *start, *end, *selection;
  355.  
  356.                         for (NewList(&list), end = result + 2; *end;) {
  357.  
  358.                             for (start = end; *end && (*end != 32); ++end);
  359.  
  360.                             if (node = (struct Node *)AllocVec(sizeof(struct Node), MEMF_ANY | MEMF_CLEAR)) {
  361.  
  362.                                 node->ln_Name = start;
  363.                                 AddTail(&list, node);
  364.                             }
  365.  
  366.                             if (*end)
  367.                                 *end++ = 0;
  368.                         }
  369.  
  370.                         // insert user selection into text
  371.  
  372.                         if (selection = ShowSpell(apiMsg->api_Screen, &list)) {
  373.  
  374.                             UWORD newLen = strlen(selection);
  375.  
  376.                             if (newLen != wordLen) {
  377.  
  378.                                 movmem(next + wordLen, next + newLen, config->CurrentLen - (next - buffer));
  379.  
  380.                                 config->CurrentLen += (newLen - wordLen);
  381.                                 config->Column     += (newLen - wordLen);
  382.  
  383.                                 while (config->Column > config->CurrentLen)
  384.                                     buffer[(config->CurrentLen)++] = ' ';
  385.                             }
  386.  
  387.                             movmem(selection, next, newLen);
  388.  
  389.                             // make GoldED redisplay the current line
  390.  
  391.                             apiMsg->api_Refresh |= API_REFRESH_LINE;
  392.                         }
  393.  
  394.                         for (node = list.lh_Head; nextNode = node->ln_Succ; node = nextNode)
  395.                             FreeVec(node);
  396.                     }
  397.                 }
  398.             }
  399.         }
  400.     }
  401. }
  402.  
  403. ///
  404. /// "gui"
  405.  
  406. /* --------------------------------- ShowSpell ---------------------------------
  407.  
  408.  Show ISpell suggestions. Return user selection or NULL.
  409.  Afficher les suggestions de ISpell. Retourne la sélection de l'utilisateur ou NULL.
  410.  
  411. */
  412.  
  413. char *
  414. ShowSpell(screen, list)
  415.  
  416. char        *screen;
  417. struct List *list;
  418. {
  419.     char *result = NULL;
  420.  
  421.     struct Screen *scr;
  422.  
  423.     if (scr = LockPubScreen(screen)) {
  424.  
  425.         struct TextFont *font;
  426.  
  427.         if (font = OpenDiskFont(scr->Font)) {
  428.  
  429.             APTR visualInfo;
  430.  
  431.             if (visualInfo = GetVisualInfoA(scr, NULL )) {
  432.  
  433.                 struct Gadget *context, *glist, *gad;
  434.  
  435.                 if (context = CreateContext(&glist)) {
  436.  
  437.                     UWORD  ww, wh, offX, offY;
  438.                     LONG   displayWidth, displayHeight;
  439.  
  440.                     struct Window *win;
  441.  
  442.                     offX  = scr->WBorLeft;
  443.                     offY  = scr->RastPort.TxHeight + scr->WBorTop + 1;
  444.  
  445.                     struct NewGadget newGad = {
  446.                     
  447.                         offX,
  448.                         offY,
  449.                         ComputeX(font, 221),
  450.                         ComputeY(font, 156),
  451.                         NULL, scr->Font, 0, 0, visualInfo, 0
  452.                     };
  453.  
  454.                     gad = CreateGadget(LISTVIEW_KIND, context, &newGad, GTLV_ShowSelected, NULL, GTLV_Labels, list, GTLV_Selected, 0, TAG_DONE);
  455.  
  456.                     rtGetVScreenSize(scr, &displayWidth, &displayHeight);
  457.  
  458.                     ww = ComputeX(font, 221);
  459.                     wh = ComputeY(font, 156);
  460.  
  461.                     if (win = OpenWindowTags( NULL,
  462.  
  463.                         WA_Left,      ((displayWidth  - ww)>>1) - scr->ViewPort.DxOffset,
  464.                         WA_Top,       ((displayHeight - wh)>>1) - scr->ViewPort.DyOffset,
  465.                         WA_Width,     ww + offX + scr->WBorRight,
  466.                         WA_Height,    wh + offY + scr->WBorBottom,
  467.                         WA_IDCMP,     LISTVIEWIDCMP | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY  | IDCMP_RAWKEY,
  468.                         WA_Flags,     WFLG_DRAGBAR  | WFLG_DEPTHGADGET  | WFLG_CLOSEGADGET  | WFLG_SMART_REFRESH | WFLG_ACTIVATE,
  469.                         WA_Gadgets,   glist,
  470.                         WA_Title,     "ISpell",
  471.                         WA_PubScreen, scr,
  472.                         TAG_DONE 
  473.  
  474.                      )) {
  475.  
  476.                         ULONG class;
  477.                         UWORD active;
  478.  
  479.                         active = 0;
  480.                         result = list->lh_Head->ln_Name;
  481.  
  482.                         struct IntuiMessage *msg;
  483.                         struct Node         *node;
  484.  
  485.                         GT_RefreshWindow(win, NULL);
  486.  
  487.  
  488.                         do {
  489.  
  490.                             while (!(msg = GT_GetIMsg(win->UserPort)))
  491.                                 WaitPort(win->UserPort);
  492.  
  493.                             switch (class = msg->Class) {
  494.  
  495.                                 case RAWKEY:
  496.  
  497.                                     WORD step = (msg->Code == CURSORUP) ? -1 : 1;
  498.  
  499.                                     if (node = SearchNode(list, active + step)) {
  500.  
  501.                                         active += step;
  502.                                         result  = node->ln_Name;
  503.  
  504.                                         GT_SetGadgetAttrs(gad, win, NULL, GTLV_Selected, active, GTLV_MakeVisible, active, TAG_DONE);
  505.                                     }
  506.  
  507.                                     break;
  508.  
  509.                                 case IDCMP_VANILLAKEY:
  510.  
  511.                                     if (msg->Code == 27)
  512.                                         class  = CLOSEWINDOW;
  513.  
  514.                                     if (msg->Code == 13)
  515.                                         class = IDCMP_GADGETUP;
  516.  
  517.                                     break;
  518.  
  519.                                 case IDCMP_GADGETUP:
  520.  
  521.                                     result = SearchNode(list, active = msg->Code)->ln_Name;
  522.                                     break;
  523.                             }
  524.  
  525.                             GT_ReplyIMsg(msg);
  526.  
  527.                         } while ((class & (GADGETUP | CLOSEWINDOW)) == NULL);
  528.  
  529.                         if (class == CLOSEWINDOW)
  530.                             result = NULL;
  531.  
  532.                         CloseWindow(win);
  533.                     }
  534.                 }
  535.                 FreeVisualInfo(visualInfo);
  536.             }
  537.         }
  538.         UnlockPubScreen(screen, scr);
  539.     }
  540.  
  541.     return(result);
  542. }
  543.  
  544. /* --------------------------------- ComputeX ----------------------------------
  545.  
  546.  Resize element of width <value> according to current font
  547.  Redimensionner l'élément de largeur <valeur> selon la police actuelle
  548.  
  549. */
  550.  
  551. UWORD 
  552. ComputeX(font, value)
  553.  
  554. UWORD  value;
  555. struct TextFont *font;
  556. {
  557.     return((font->tf_XSize * value) / 8);
  558. }          
  559.  
  560. /* --------------------------------- ComputeY ----------------------------------
  561.  
  562.  Resize element of height <value> according to current font
  563.  Redimensionner l'élément de hauteur <valeur> selon la police actuelle
  564.  
  565. */
  566.  
  567. UWORD 
  568. ComputeY(font, value)
  569.  
  570. UWORD  value;
  571. struct TextFont *font;
  572. {
  573.     return((font->tf_YSize * value) / 8);
  574. }
  575.  
  576. ///
  577. /// "misc"
  578.  
  579. /* ---------------------------------- SearchNode --------------------------------
  580.  
  581.  Return pointer to node if ordinal number (0, ...) is known.
  582.  Retourne le pointeur sur la node si un nombre ordinal (0, ...) est connu.
  583.  
  584. */
  585.  
  586. struct Node *
  587. SearchNode(list, ordinal)
  588.  
  589. struct List *list;
  590. UWORD  ordinal;
  591. {
  592.     struct Node *node;
  593.  
  594.     for (node = list->lh_Head; node->ln_Succ; --ordinal, node = node->ln_Succ)
  595.         if (!ordinal)
  596.             return(node);
  597.  
  598.     return(NULL);
  599. }
  600.  
  601. /* ----------------------------------- Beep ------------------------------------
  602.  
  603.  Short audible beep
  604.  Bip sonore bref
  605.  
  606. */
  607.  
  608. void
  609. Beep()
  610. {
  611.     struct IOAudio *audioIO;
  612.  
  613.     if (audioIO = (struct IOAudio *)AllocVec(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR)) {
  614.  
  615.         struct MsgPort *audioMP;
  616.  
  617.         if (audioMP = CreateMsgPort()) {
  618.  
  619.             UBYTE whichannel[] = { 1, 2, 4, 8 };
  620.  
  621.             audioIO->ioa_Request.io_Message.mn_ReplyPort   = audioMP;
  622.             audioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
  623.             audioIO->ioa_Request.io_Command                = ADCMD_ALLOCATE;
  624.             audioIO->ioa_Request.io_Flags                  = ADIOF_NOWAIT;
  625.             audioIO->ioa_AllocKey                          = 0;
  626.             audioIO->ioa_Data                              = whichannel;
  627.             audioIO->ioa_Length                            = sizeof(whichannel);
  628.  
  629.             if (!OpenDevice("audio.device", 0, (struct IORequest *)audioIO, 0)) {
  630.  
  631.                 __chip const static UBYTE waveptr[2] = {127, -127};
  632.  
  633.                 audioIO->ioa_Request.io_Message.mn_ReplyPort = audioMP;
  634.                 audioIO->ioa_Request.io_Command              = CMD_WRITE;
  635.                 audioIO->ioa_Request.io_Flags                = ADIOF_PERVOL;
  636.  
  637.                 audioIO->ioa_Data   = waveptr;
  638.                 audioIO->ioa_Length = 2;
  639.                 audioIO->ioa_Period = 1015;
  640.                 audioIO->ioa_Volume = 32;
  641.                 audioIO->ioa_Cycles = 60; // 44;
  642.  
  643.                 BeginIO((struct IORequest *)audioIO );
  644.  
  645.                 WaitPort(audioMP);
  646.                 GetMsg  (audioMP);
  647.  
  648.                 CloseDevice((struct IORequest *)audioIO);
  649.             }
  650.             DeleteMsgPort(audioMP);
  651.         }
  652.         FreeVec(audioIO);
  653.     }
  654. }
  655.  
  656. ///
  657. /// "arexx"
  658.  
  659. /* ---------------------------------- SendRexxCommand -------------------------
  660.  
  661.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  662.  
  663.  Envoyer un message ARexx & attendre une réponse. Retourne un pointeur sur le
  664.  résultat ou NULL.
  665.  
  666. */
  667.  
  668. ULONG *
  669. SendRexxCommand(port, cmd, replyPort, buffer)
  670.  
  671. char   *cmd, *port, *buffer;
  672. struct MsgPort *replyPort;
  673. {
  674.     struct MsgPort *rexxport;
  675.  
  676.     Forbid();
  677.  
  678.     if (rexxport = FindPort(port)) {
  679.  
  680.         struct RexxMsg *rexxMsg, *answer;
  681.  
  682.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  683.  
  684.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  685.  
  686.                 static ULONG result;
  687.  
  688.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  689.  
  690.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  691.  
  692.                 do {
  693.                     
  694.                     WaitPort(replyPort);
  695.  
  696.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  697.                         result = answer->rm_Result1;
  698.  
  699.                 } while (!answer);
  700.  
  701.                 Permit();
  702.  
  703.                 if (answer->rm_Result1 == RC_OK) {
  704.  
  705.                     if (answer->rm_Result2) {
  706.  
  707.                         if (buffer)
  708.                             strcpy(buffer, (char *)answer->rm_Result2);
  709.  
  710.                         DeleteArgstring((char *)answer->rm_Result2);
  711.                     }
  712.                 }
  713.  
  714.                 DeleteArgstring((char *)ARG0(answer));
  715.  
  716.                 DeleteRexxMsg(answer);
  717.  
  718.                 return(&result);
  719.             }
  720.         }
  721.     }
  722.  
  723.     Permit();
  724.  
  725.     return(NULL);
  726. }
  727.  
  728. ///
  729.